package otherapi.fastjson;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ObjectNode;
import entity.User;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

/**
 * @author LiDong
 * @version 1.0.0
 * @createTime 9/29/2022 5:54 PM
 */
public class FastJsonTest {

    private static final Logger logger = LoggerFactory.getLogger(FastJsonTest.class);

    private static final String defaultDateFormat = "yyyy-MM-dd HH:mm:ss";

    private static ConcurrentHashMap<String, ObjectMapper> mapperMap = new ConcurrentHashMap<>();

    @Test
    public void test1() {
        UserTest user = new UserTest();
        // user.setUserName("one");

        // user.setUsername("two");
        String s = "{\"username\":\"two\"}";

        logger.info(s);
        UserTest userTest = JSON.parseObject(s, UserTest.class);

        logger.info(userTest.toString());
    }

    @Test
    public void test2() {
        String s = "{\"id\":\"1\",\"name\":\"zhangsan\",\"age\":\"222\",\"item\":\"test1\"}";
        PeopleDO peopleDO = JSON.parseObject(s, PeopleDO.class);

        ObjectMapper o = new ObjectMapper();
        try {
            String writeValueAsString = o.writeValueAsString(peopleDO);
            // String s1 = JSON.toJSONString(peopleDO);
            PeopleDO peopleDO1 = JSON.parseObject(s, PeopleDO.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        logger.info(peopleDO.toString());
    }

    @Test
    public void test3() {
        JSONObject jsonObject = new JSONObject();
        String d = jsonObject.getString("d");
        Boolean a = jsonObject.getBoolean("a");
        int b = jsonObject.getIntValue("b");
        float c = jsonObject.getFloatValue("c");

        Map<String, Object> tempMap = new HashMap<>();
        a = (Boolean) tempMap.get("a");
        b = (int) tempMap.get("b");
        c = (float) tempMap.get("c");
        logger.info("test");
    }

    @Test
    public void test6() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("c",new Float("1.00"));
        jsonObject.put("e", false);
        Double g =new Double("1.00");
        String d = jsonObject.getString("d");
        Boolean a = jsonObject.getBoolean("a");
        boolean e = Boolean.FALSE.equals(jsonObject.getBoolean("e"));
        Boolean f = !jsonObject.getBoolean("f");
        int b = jsonObject.getIntValue("b");
        float c = jsonObject.getFloatValue("c");
        logger.info("test");
    }


    @Test
    public void test4() {
        ObjectNode jsonObject = new ObjectNode(null);
        String d = jsonObject.get("d").asText();
        Boolean a = jsonObject.get("a").asBoolean();
        int b = jsonObject.get("b").asInt();
        float c = jsonObject.get("c").asLong();
        logger.info("test");
        Map<String,Object> map = new HashMap<String,Object>();
        if (map.get("test") != null) {
            String test = String.valueOf(map.get("test"));
        }
        String e = String.valueOf(Optional.ofNullable(map.get("test")).orElse(""));
    }

    @Test
    public void test5() {
        ObjectNode objectNode = new ObjectNode(null);
        double a = objectNode.path("a").asDouble(0);
        float b = (float) a;
        logger.info("b:{}", b);
    }

    @Test
    public void test7() {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("a",list);
    }

    @Test
    public void test8() throws ParseException {
        String str1 = "1970-01-02";
        String str2 = "1971-01-01";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date1 = simpleDateFormat.parse(str1);
        Date date2 = simpleDateFormat.parse(str2);
        String tempStr1 = JSON.toJSONString(date1);
        // 是个 int 类型的值
        int t1 = Integer.parseInt(tempStr1);
        String tempStr2 = JSON.toJSONString(date2);
        // 是个 long 类型的值
        long t2 = Long.parseLong(tempStr2);
        logger.info(tempStr1);
        logger.info(tempStr2);
    }

    /**
     * 将json字符串转换成指定类型对象
     */
    public static <T> T parseObject(String content, Class<T> valueType) {
        if (!StringUtils.hasText(content)) {
            return null;
        }

        ObjectMapper objectMapper = getObjectMapper();

        try {
            return objectMapper.readValue(content, valueType);
        } catch (JsonMappingException e) {
            logger.error("JsonMappingException: ", e);
        } catch (JsonProcessingException e) {
            logger.error("JsonProcessingException: ", e);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static ObjectMapper getObjectMapper() {
        return getObjectMapper(defaultDateFormat, false);
    }

    private static ObjectMapper getObjectMapper(String dataFormatString, boolean prettyFormat) {
        String key = prettyFormat ? "P#" + dataFormatString : dataFormatString;

        ObjectMapper objectMapper = mapperMap.get(key);
        if (objectMapper != null) {
            return objectMapper;
        }

        mapperMap.putIfAbsent(key, new ObjectMapper());
        objectMapper = mapperMap.get(key);

        // 不含null值
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 忽略未知映射
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 日期格式
        objectMapper.setDateFormat(new SimpleDateFormat(dataFormatString));
        // 美化输出
        if (prettyFormat) {
            objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        }

        // 处理 BigDecimal 精度问题
        SimpleModule module = new SimpleModule();
        module.addSerializer(BigDecimal.class, new JsonSerializer<BigDecimal>() {
            public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers)
                    throws IOException {
                if (value == null) {
                    gen.writeNull();
                } else {
                    String valStr = value.toPlainString();
                    if (valStr.length() > 16) {
                        gen.writeString(valStr);
                    } else {
                        gen.writeNumber(value);
                    }
                }
            }
        });

        // 处理 Double 科学计数法
        module.addSerializer(Double.class, new JsonSerializer<Double>() {
            public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                if (value == null) {
                    gen.writeNull();
                } else {
                    String valStr = value.toString();
                    if (valStr.contains("E")) {
                        gen.writeString(new BigDecimal(valStr).toPlainString());
                    } else {
                        gen.writeNumber(value);
                    }
                }
            }
        });

        objectMapper.registerModule(module);

        return objectMapper;
    }

    /**
     * 将json字符串转换成ObjectNode对象
     */
    public static ObjectNode parseObject(String content) {
        return parseObject(content, ObjectNode.class);
    }
}
